package com.simple.system.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.simple.system.util.JwtUtils;
import com.simple.system.util.PermissionUtils;
import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class JwtFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(JwtFilter.class);
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 记录更多请求信息
        String requestMethod = httpRequest.getMethod();
        String requestUrl = httpRequest.getRequestURI().trim();
        String queryString = httpRequest.getQueryString();
        logger.info("Request Method: {}, URL: {}, Query String: {}", requestMethod, requestUrl, queryString);

        if ("/users/login".equalsIgnoreCase(requestUrl) || "/users/register".equalsIgnoreCase(requestUrl)
                || "/users/hello".equalsIgnoreCase(requestUrl) || "/captcha".equalsIgnoreCase(requestUrl)) {
            logger.info("Request to {} bypassing JWT validation.", requestUrl);
            filterChain.doFilter(request, response);
            return;
        }

        String authorizationHeader = httpRequest.getHeader("Authorization");
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            String[] parts = authorizationHeader.split(" ");
            if (parts.length == 2) {
                String token = parts[1];
                try {
                    Claims claims = JwtUtils.validateToken(token);
                    Object userId = claims.get("userId");
                    if (userId != null) {
                        httpRequest.setAttribute("userId", userId);
                        List<GrantedAuthority> authorities = PermissionUtils.getAllPermissions();
                        // 关键步骤：设置 SecurityContext
                        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                                userId, null, authorities
                        );
                        authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
                        SecurityContextHolder.getContext().setAuthentication(authToken);
                    } else {
                        sendUnauthorizedResponse(httpResponse, 403, "登录失效，请重新登录");
                        return;
                    }
                } catch (Exception e) {
                    sendUnauthorizedResponse(httpResponse, 403, "登录失效或无权访问");
                    return;
                }
            } else {
                sendUnauthorizedResponse(httpResponse, 403, "Authorization 头格式错误");
                return;
            }
        } else {
            sendUnauthorizedResponse(httpResponse, 403, "参数中未传递 Authorization");
            return;
        }

        try {
            filterChain.doFilter(request, response);
//            int status = httpResponse.getStatus();
//            if (status >= 400 && status < 600) {
//                // 处理非成功的状态码，比如记录日志、返回更友好的错误信息等
//                logger.error("Response status code is: {}", status);
//                // 可以根据状态码进一步处理，例如发送自定义错误响应
//                sendUnauthorizedResponse(httpResponse, status, "Some error message based on the status");
//            }
        } catch (Exception e) {
            logger.error("Exception occurred during request processing", e);
            sendUnauthorizedResponse(httpResponse, 500, "请求处理过程中发生错误");
        }
    }

    private void sendUnauthorizedResponse(HttpServletResponse httpResponse, int code, String message) throws IOException {
        httpResponse.setStatus(code);
        httpResponse.setContentType("application/json;charset=UTF-8");
        Map<String, Object> errorResponse = new HashMap<>();
        errorResponse.put("code", code);
        errorResponse.put("msg", message);
        httpResponse.getWriter().write(objectMapper.writeValueAsString(errorResponse));
    }
}